home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / nos042_s / cmdparse.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  8KB  |  406 lines

  1. /* Parse command line, set up command arguments Unix-style, and call function.
  2.  * Note: argument is modified (delimiters are overwritten with nulls)
  3.  *
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  *
  6.  * Improved error handling by Brian Boesch of Stanford University
  7.  * Feb '91 - Bill Simpson
  8.  *        bit16cmd for PPP
  9.  * Mar '91 - Glenn McGregor
  10.  *        handle string escaped sequences
  11.  */
  12.  
  13. /****************************************************************************
  14. *    $Id: cmdparse.c 1.3 93/07/16 11:43:18 ROOT_DOS Exp $
  15. *    24 Aug 92    1.2        CMS    Expand environment variables.                    *
  16. *    10 Jul 93    1.3        GT    Fix warnings.                                    *
  17. *
  18. *  ATARI Version by David Nash - dnash@chaos.demon.co.uk
  19. *  
  20. *****************************************************************************/
  21.  
  22. #include <stdio.h>
  23. #include "global.h"
  24. #include "proc.h"
  25. #include "cmdparse.h"
  26.  
  27. struct boolcmd {
  28.     char *str;    /* Token */
  29.     int val;    /* Value */
  30. };
  31.  
  32. static struct boolcmd Boolcmds[] = {
  33.     { "y",        1},    /* Synonyms for "true" */
  34.     { "yes",        1},
  35.     { "true",    1},
  36.     { "on",        1},
  37.     { "1",        1},
  38.     { "set",        1},
  39.     { "enable",    1},
  40.  
  41.     {"n",            0},    /* Synonyms for "false" */
  42.     {"no",        0},
  43.     {"false",    0},
  44.     {"off",        0},
  45.     {"0",            0},
  46.     {"clear",    0},
  47.     {"disable",    0},
  48.     {NULLCHAR}
  49. };
  50.  
  51. static char *stringparse __ARGS((char *line));
  52.  
  53. static char *
  54. stringparse(line)
  55. char *line;
  56. {
  57.     register char *cp = line;
  58.     unsigned long num;
  59.  
  60.     while ( *line != '\0' && *line != '\"' ) {
  61.         if ( *line == '\\' ) {
  62.             line++;
  63.             switch ( *line++ ) {
  64.             case 'n':
  65.                 *cp++ = '\n';
  66.                 break;
  67.             case 't':
  68.                 *cp++ = '\t';
  69.                 break;
  70.             case 'v':
  71.                 *cp++ = '\v';
  72.                 break;
  73.             case 'b':
  74.                 *cp++ = '\b';
  75.                 break;
  76.             case 'r':
  77.                 *cp++ = '\r';
  78.                 break;
  79.             case 'f':
  80.                 *cp++ = '\f';
  81.                 break;
  82.             case 'a':
  83.                 *cp++ = '\a';
  84.                 break;
  85.             case '\\':
  86.                 *cp++ = '\\';
  87.                 break;
  88.             case '\?':
  89.                 *cp++ = '\?';
  90.                 break;
  91.             case '\'':
  92.                 *cp++ = '\'';
  93.                 break;
  94.             case '\"':
  95.                 *cp++ = '\"';
  96.                 break;
  97.             case 'x':
  98.                 num = strtoul( --line, &line, 16 );
  99.                 *cp++ = (char) num;
  100.                 break;
  101.             case '0':
  102.             case '1':
  103.             case '2':
  104.             case '3':
  105.             case '4':
  106.             case '5':
  107.             case '6':
  108.             case '7':
  109.                 num = strtoul( --line, &line, 8 );
  110.                 *cp++ = (char) num;
  111.                 break;
  112.             case '\0':
  113.                 return NULLCHAR;
  114.             default:
  115.                 *cp++ = *(line - 1);
  116.                 break;
  117.             };
  118.         } else {
  119.             *cp++ = *line++;
  120.         }
  121.     }
  122.  
  123.     if ( *line == '\"' )
  124.         line++;     /* skip final quote */
  125.     *cp = '\0';        /* terminate string */
  126.     return line;
  127. }
  128.  
  129. int
  130. cmdparse(cmds,line,p)
  131. struct cmds cmds[];
  132. char *line;
  133. void *p;
  134. {
  135.     struct cmds *cmdp;
  136.     char *argv[NARG],*cp;
  137.     char **pargv;
  138.     int argc,i;
  139.  
  140.     /* Remove cr/lf */
  141.     rip(line);
  142.  
  143.     for(argc = 0;argc < NARG;argc++)     
  144.         argv[argc] = NULLCHAR;
  145.  
  146.     for(argc = 0;argc < NARG;){
  147.         register int qflag = FALSE;
  148.  
  149.         /* Skip leading white space */
  150.         while(*line == ' ' || *line == '\t')
  151.             line++;
  152.         if(*line == '\0')
  153.             break;
  154.         /* return if comment character first non-white */
  155.         if ( argc == 0  &&  *line == '#' )
  156.             return 0;
  157.         /* Check for quoted token */
  158.         if(*line == '"'){
  159.             line++;    /* Suppress quote */
  160.             qflag = TRUE;
  161.         }
  162.         argv[argc++] = line;    /* Beginning of token */
  163.  
  164.         if(qflag){
  165.             /* Find terminating delimiter */
  166.             if((line = stringparse(line)) == NULLCHAR){
  167.                 return -1;
  168.             }
  169.         } else {
  170.             /* Find space or tab. If not present,
  171.              * then we've already found the last
  172.              * token.
  173.              */
  174.             if((cp = strchr(line,' ')) == NULLCHAR
  175.              && (cp = strchr(line,'\t')) == NULLCHAR){
  176.                 break;
  177.             }
  178.             *cp++ = '\0';
  179.             line = cp;
  180.         }
  181.     }
  182.     if (argc < 1) {        /* empty command line */
  183.         argc = 1;
  184.         argv[0] = "";
  185.     }
  186.     /* Check for $ commands and substitute environment variables */
  187.     for (i = 0; i < argc; i++) {
  188.         char *p;
  189.         int j;
  190.         if (*argv[i] == '$') {
  191.             strupr(argv[i]);
  192.             if ((p = getenv(argv[i] + 1)) != NULL && *p)
  193.                 argv[i] = p;
  194.             else {
  195.                 for (j = i + 1; j < argc; j++)
  196.                     argv[j - 1] = argv[j];
  197.                 argv[argc - 1] = NULL;
  198.                 argc--;
  199.             }
  200.         }
  201.     }
  202.     if (*argv[0] == '#')
  203.         return 0;
  204.     /* Look up command in table; prefix matches are OK */
  205.     for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
  206.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0)
  207.             break;
  208.     }
  209.     if(cmdp->name == NULLCHAR) {
  210.         if(cmdp->argc_errmsg != NULLCHAR)
  211.             tprintf("%s\n",cmdp->argc_errmsg);
  212.         return -1;
  213.     } else {
  214.         if(argc < cmdp->argcmin) {
  215.             /* Insufficient arguments */
  216.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  217.             return -1;
  218.         } else {
  219.             if(cmdp->stksize == 0){
  220.                 return (*cmdp->func)(argc,argv,p);
  221.             } else {
  222.                 /* Make private copy of argv and args,
  223.                  * spawn off subprocess and return.
  224.                  */
  225.                 pargv = (char **)callocw(argc,sizeof(char *));
  226.                 for(i=0;i<argc;i++) 
  227.                     pargv[i] = strdup(argv[i]);
  228.    
  229.                 newproc(cmdp->name,cmdp->stksize,
  230.                 (void (*)())cmdp->func,argc,pargv,p,1);
  231.                 return(0);
  232.             }
  233.         }
  234.     }
  235. }
  236.  
  237. /* Call a subcommand based on the first token in an already-parsed line */
  238. int
  239. subcmd(tab,argc,argv,p)
  240. struct cmds tab[];
  241. int argc;
  242. char *argv[];
  243. void *p;
  244. {
  245.     register struct cmds *cmdp;
  246.     char **pargv;
  247.     int found = 0;
  248.     int i;
  249.  
  250.     /* Strip off first token and pass rest of line to subcommand */
  251.     if (argc < 2) {
  252.         if (argc < 1)
  253.             tprintf("SUBCMD - Don't know what to do?\n");
  254.         else
  255.             tprintf("\"%s\" - takes at least one argument\n",argv[0]);
  256.         return -1;
  257.     }
  258.     argc--;
  259.     argv++;
  260.     for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  261.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0){
  262.             found = 1;
  263.             break;
  264.         }
  265.     }
  266.     if(!found){
  267.         tprintf("valid subcommands:");
  268.         for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++)
  269.             if(tprintf(" %s",cmdp->name) == EOF)
  270.                 return -1;
  271.         tprintf("\n");
  272.         return -1;
  273.     }
  274.     if(argc < cmdp->argcmin){
  275.         if(cmdp->argc_errmsg != NULLCHAR)
  276.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  277.         return -1;
  278.     }
  279.     if(cmdp->stksize == 0){
  280.         return (*cmdp->func)(argc,argv,p);
  281.     } else {
  282.         /* Make private copy of argv and args */
  283.         pargv = (char **)callocw(argc,sizeof(char *));
  284.         for(i=0;i<argc;i++)
  285.             pargv[i] = strdup(argv[i]);
  286.         newproc(cmdp->name,cmdp->stksize,
  287.          (void (*)())cmdp->func,argc,pargv,p,1);
  288.         return(0);
  289.     }
  290. }
  291.  
  292. /* Subroutine for setting and displaying boolean flags */
  293. int
  294. setbool(var,label,argc,argv)
  295. int *var;
  296. char *label;
  297. int argc;
  298. char *argv[];
  299. {
  300.     struct boolcmd *bc;
  301.  
  302.     if(argc < 2){
  303.         tprintf("%s: %s\n",label,*var ? "on":"off");
  304.         return 0;
  305.     }
  306.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++){
  307.         if(strcmpi(argv[1],bc->str) == 0){
  308.             *var = bc->val;
  309.             return 0;
  310.         }
  311.     }
  312.     tprintf("Valid options:");
  313.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  314.         if(tprintf(" %s",bc->str) == EOF)
  315.             return 1;
  316.     tprintf("\n");
  317.     return 1;
  318. }
  319.  
  320.  
  321. /* Subroutine for setting and displaying bit values */
  322. int bit16cmd(
  323.     int16 *bits,
  324.     int16 mask,
  325.     char *label,
  326.     int argc,
  327.     char *argv[])
  328. {
  329.     int doing = (*bits & mask);
  330.     int result = setbool( &doing, label, argc, argv );
  331.  
  332.     if ( !result ) {
  333.         if ( doing )
  334.             *bits |= mask;
  335.         else
  336.             *bits &= ~mask;
  337.     }
  338.     return result;
  339. }
  340.  
  341.  
  342. /* Subroutine for setting and displaying long variables */
  343. int
  344. setlong(var,label,argc,argv)
  345. long *var;
  346. char *label;
  347. int argc;
  348. char *argv[];
  349. {
  350.     if(argc < 2)
  351.         tprintf("%s: %ld\n",label,*var);
  352.     else
  353.         *var = atol(argv[1]);
  354.  
  355.     return 0;
  356. }
  357. /* Subroutine for setting and displaying short variables */
  358. int
  359. setshort(var,label,argc,argv)
  360. unsigned short *var;
  361. char *label;
  362. int argc;
  363. char *argv[];
  364. {
  365.     if(argc < 2)
  366.         tprintf("%s: %u\n",label,*var);
  367.     else
  368.         *var = atoi(argv[1]);
  369.  
  370.     return 0;
  371. }
  372. /* Subroutine for setting and displaying integer variables */
  373. int
  374. setint(var,label,argc,argv)
  375. int *var;
  376. char *label;
  377. int argc;
  378. char *argv[];
  379. {
  380.     if(argc < 2)
  381.         tprintf("%s: %i\n",label,*var);
  382.     else
  383.         *var = atoi(argv[1]);
  384.  
  385.     return 0;
  386. }
  387.  
  388. /* Subroutine for setting and displaying unsigned integer variables */
  389. int
  390. setuns(var,label,argc,argv)
  391. unsigned *var;
  392. char *label;
  393. int argc;
  394. char *argv[];
  395. {
  396.     if(argc < 2)
  397.         tprintf("%s: %u\n",label,*var);
  398.     else
  399.         *var = atoi(argv[1]);
  400.  
  401.     return 0;
  402. }
  403.  
  404.  
  405.  
  406.